"""
    python实现jwt
"""
import base64
import hmac
import time
import json
import copy


class Jwt:
    def __init__(self):
        pass

    @staticmethod
    def base64_encode(string):
        """
        功能函数: base64编码
        :param string: 欲编码的字符串
        :return: 编码后的字节串
        """
        # 等于号=在传输过程中没有任何意义,并且占用带宽
        # 故去掉=,节省带宽
        return base64.urlsafe_b64encode(string.encode()).replace(b'=', b'')

    @staticmethod
    def base64_decode(b64_string):
        """
        功能函数: base64解码
        :param b64_string: base64的字符串
        :return: 解码后的结果
        """
        # base64_string: zhao liyi ngi  11%4=3
        result = len(b64_string) % 4
        if result != 0:
            b64_string += "=" * (4-result)

        return base64.urlsafe_b64decode(b64_string.encode()).decode()

    @staticmethod
    def make_token(payload, key, expire=300):
        """生成token"""
        # 1.header
        header = {"alg": "HS256", "typ": "JWT"}
        header = json.dumps(header, separators=(",", ":"), sort_keys=True)
        part1 = Jwt.base64_encode(header)

        # 2.payload
        payload_dict = copy.deepcopy(payload)

        payload_dict['exp'] = time.time() + expire
        payload_dict = json.dumps(payload_dict, separators=(",", ":"), sort_keys=True)
        part2 = Jwt.base64_encode(payload_dict)

        # 3.sign
        part1_2 = part1 + b'.' + part2
        sign = hmac.new(key.encode(), part1_2, digestmod="SHA256").hexdigest()
        sign = Jwt.base64_encode(sign)

        return (part1_2 + b'.' + sign).decode()

    @staticmethod
    def check_token(token, key):
        """
        功能函数:校验token
        :param token: 字符串
        :return:
        """
        # 1.校验token合法性
        #   1.1 前两部分结合密钥进行hmac加密,结果和第三部分比较
        #   相等: token合法
        #   不相等: token不合法
        # 2.校验有效期
        part1, part2, user_part3 = token.split('.')
        sign = hmac.new(key.encode(),
                        (part1+'.'+part2).encode(),
                        digestmod="SHA256").hexdigest()
        server_part3 = Jwt.base64_encode(sign)
        # 判断 服务器生成的第三部分 和 用户的第三部分是否相等
        if user_part3 != server_part3.decode():
            # token不合法
            raise

        # 判断有效期
        part2_dict = Jwt.base64_decode(part2)
        # part2_dict: {"username":xxx, "exp":xxx}
        part2_dict = json.loads(part2_dict)

        exp = part2_dict["exp"]
        now = time.time()
        if now > exp:
            # 已过期
            raise

        return part2_dict


if __name__ == '__main__':
    token = Jwt.make_token(
        payload={"username": "liying"},
        key="1234567",
        expire=5
    )
    print(token)
    time.sleep(6)
    print(Jwt.check_token(token, '1234567'))

















